/*
 * FaceCat图形通讯框架
 * 著作权编号:2015SR229355+2020SR0266727
 * 上海卷卷猫信息技术有限公司
 */

#include "../../stdafx.h"
#include "../../include/core/FCView.h"
#include "../../include/core/FCPaint.h"

namespace FaceCat{
	FCAtrEx::FCAtrEx(){
        m_maximumSize.cx = 100000;
        m_maximumSize.cy = 100000;
        m_minimumSize.cx = 0;
        m_minimumSize.cy = 0;
        m_percentLocation = 0;
        m_percentSize = 0;
        m_region.left = 0;
        m_region.top = 0;
        m_region.right = 0;
        m_region.bottom = 0;
        m_useRegion = false;
		m_allowDrag = false;
        m_allowPreviewsEvent = false;
        m_autoEllipsis = false;
        m_autoSize = false;
        m_tabIndex = 0;
        m_tabStop = false;
        m_tag = 0;
        m_cornerRadius = 0;
        m_cursor = FCCursors_Arrow;
        m_displayOffset = true;
        m_isDragging = false;
        m_isWindow = false;
        m_dock = FCDockStyle_None;
		m_canFocus = true;
		m_borderWidth = 1;
    }

    FCAtrEx::~FCAtrEx(){
        for(int i = 0; i < m_events.size(); i++){
            delete m_events.getValue(i);
        }
        m_events.clear();
        for(int i = 0; i < m_invokes.size(); i++){
            delete m_invokes.getValue(i);
        }
        m_invokes.clear();
        if(m_percentLocation){
            delete m_percentLocation;
            m_percentLocation = 0;
        }
        if(m_percentSize){
            delete m_percentSize;
            m_percentSize = 0;
        }
    }

	void FCView::callEvents(String eventName){
		if(m_atrEx && m_atrEx->m_events.size() > 0){
			if(m_atrEx->m_events.containsKey(eventName)){
                ArrayList<Object> *events = m_atrEx->m_events.get(eventName);
                ArrayList<Object> *invokes = m_atrEx->m_invokes.get(eventName);
				int eventSize = (int)events->size();
				for(int i = 0; i < eventSize; i++){
					FCEventCallBack *func = (FCEventCallBack*)(events->get(i));
                    func->callEvent(eventName, this, invokes->get(i));
				}
			}
		}
	}

	void FCView::callInvokeEvents(String eventName, Object args){
		if(m_atrEx && m_atrEx->m_events.size() > 0){
			if(m_atrEx->m_events.containsKey(eventName)){
                ArrayList<Object> *events = m_atrEx->m_events.get(eventName);
                ArrayList<Object> *invokes = m_atrEx->m_invokes.get(eventName);
				int eventSize = (int)events->size();
				for(int i = 0; i < eventSize; i++){
					FCInvokeEventCallBack *func = (FCInvokeEventCallBack*)(events->get(i));
                    func->callInvokeEvent(eventName, this, args, invokes->get(i));
				}
			}
		}
	}

	void FCView::callKeyEvents(String eventName, char key){
		if(m_atrEx && m_atrEx->m_events.size() > 0){
			if(m_atrEx->m_events.containsKey(eventName)){
                ArrayList<Object> *events = m_atrEx->m_events.get(eventName);
                ArrayList<Object> *invokes = m_atrEx->m_invokes.get(eventName);
				int eventSize = (int)events->size();
				for(int i = 0; i < eventSize; i++){
					FCKeyEventCallBack *func = (FCKeyEventCallBack*)(events->get(i));
                    func->callKeyEvent(eventName, this, key, invokes->get(i));
				}
			}
		}
	}

	void FCView::callTouchEvents(String eventName, FCTouchInfo touchInfo){
		if(m_atrEx && m_atrEx->m_events.size() > 0){
			if(m_atrEx->m_events.containsKey(eventName)){
                ArrayList<Object> *events = m_atrEx->m_events.get(eventName);
                ArrayList<Object> *invokes = m_atrEx->m_invokes.get(eventName);
				int eventSize = (int)events->size();
				for(int i = 0; i < eventSize; i++){
					FCTouchEventCallBack *func = (FCTouchEventCallBack*)(events->get(i));
                    func->callTouchEvent(eventName, this, touchInfo, invokes->get(i));
				}
			}
		}
	}

	bool FCView::callPaintEvents(String eventName, FCPaint *paint, const FCRect& clipRect){
		if(m_atrEx && m_atrEx->m_events.size() > 0){
			if(m_atrEx->m_events.containsKey(eventName)){
                ArrayList<Object> *events = m_atrEx->m_events.get(eventName);
                ArrayList<Object> *invokes = m_atrEx->m_invokes.get(eventName);
				int eventSize = (int)events->size();
				for(int i = 0; i < eventSize; i++){
					FCPaintEventCallBack *func = (FCPaintEventCallBack*)(events->get(i));
                    if(func->callPaintEvent(eventName, this, paint, clipRect, invokes->get(i))){
                        return true;
                    }
				}
			}
		}
		return false;
	}

	bool FCView::callPreviewsKeyEvent(String eventName, String tEventID, char key){
		if(m_atrEx && m_atrEx->m_events.size() > 0){
			if(m_atrEx->m_events.containsKey(eventName)){
                ArrayList<Object> *events = m_atrEx->m_events.get(eventName);
                ArrayList<Object> *invokes = m_atrEx->m_invokes.get(eventName);
				int eventSize = (int)events->size();
				for(int i = 0; i < eventSize; i++) {
                    FCPreviewsKeyEventCallBack *func = (FCPreviewsKeyEventCallBack *) (events->get(i));
                    if (func->callPreviewsKeyEvent(eventName, tEventID, this, key, invokes->get(i))) {
						return true;
					}
				}
			}
		}
		return false;
	}

	bool FCView::callPreviewsTouchEvent(String eventName, String tEventID, FCTouchInfo touchInfo){
		if(m_atrEx && m_atrEx->m_events.size() > 0){
			if(m_atrEx->m_events.containsKey(eventName)){
                ArrayList<Object> *events = m_atrEx->m_events.get(eventName);
                ArrayList<Object> *invokes = m_atrEx->m_invokes.get(eventName);
				int eventSize = (int)events->size();
				for(int i = 0; i < eventSize; i++){
					FCPreviewsTouchEventCallBack *func = (FCPreviewsTouchEventCallBack*)(events->get(i));
                    if(func->callPreviewsTouchEvent(eventName, tEventID, this, touchInfo, invokes->get(i))){
						return true;
					}
				}
			}
		}
		return false;
	}

	void FCView::callTimerEvents(String eventName, int timerID){
		if(m_atrEx && m_atrEx->m_events.size() > 0){
			if(m_atrEx->m_events.containsKey(eventName)){
                ArrayList<Object> *events = m_atrEx->m_events.get(eventName);
                ArrayList<Object> *invokes = m_atrEx->m_invokes.get(eventName);
				int eventSize = (int)events->size();
				for(int i = 0; i < eventSize; i++){
					FCTimerEventCallBack *func = (FCTimerEventCallBack*)(events->get(i));
                    func->callTimerEvent(eventName, this, timerID, invokes->get(i));
				}
			}
		}
	}

	Long FCView::getPaintingBackColor(){
		if (m_backColor != FCColor_None && FCColor_DisabledBack != FCColor_None){
            if (!isPaintEnabled(this)){
				return FCColor_DisabledBack;
            }
        }
        return m_backColor;
	}

	String FCView::getPaintingBackImage(){
		return getBackImage();
	}

	Long FCView::getPaintingBorderColor(){
		return m_borderColor;
	}

	Long FCView::getPaintingTextColor(){
		if (m_textColor != FCColor_Text && FCColor_DisabledText != FCColor_None){
            if (!isPaintEnabled(this)){
				return FCColor_DisabledText;
            }
        }
        return m_textColor;
	}
	
	/////////////////////////////////////////////////////////////////////////////////////////////////////////

	FCView::FCView(){
		m_align = FCHorizontalAlign_Left;
        m_backColor = FCColor_Back;
        m_borderColor = FCColor_Border;
        m_enabled = true;
        m_font = new FCFont();
        m_textColor = FCColor_Text;
        m_location.x = 0;
        m_location.y = 0;
        m_native = 0;
        m_oldSize.cx = 0;
        m_oldSize.cy = 0;
        m_opacity = 1;
        m_parent = 0;
        m_size.cx = 0;
        m_size.cy = 0;
        m_topMost = false;
        m_verticalAlign = FCVerticalAlign_Top;
        m_visible = true;
        m_atrEx = 0;
	}

	FCView::~FCView(){
		if(m_font){
			delete m_font;
			m_font = 0;
		}
		if(m_atrEx){
            delete m_atrEx;
            m_atrEx = 0;
        }
		clearViews();
		m_native = 0;
		m_parent = 0;
	}

	FCHorizontalAlign FCView::getAlign(){
		return m_align;
	}

	void FCView::setAlign(FCHorizontalAlign value){
		m_align = value;
	}

	bool FCView::allowDrag(){
		if(!m_atrEx){
            return false;
        }
        return m_atrEx->m_allowDrag;
	}

	void FCView::setAllowDrag(bool value){
		if(!m_atrEx){
            m_atrEx = new FCAtrEx;
        }
        m_atrEx->m_allowDrag = value;
	}

	bool FCView::allowPreviewsEvent(){
		if(!m_atrEx){
            return false;
        }
        return m_atrEx->m_allowPreviewsEvent;
	}

	void FCView::setAllowPreviewsEvent(bool value){
		if(!m_atrEx){
            m_atrEx = new FCAtrEx;
        }
        m_atrEx->m_allowPreviewsEvent = value;
	}

	FCAnchor FCView::getAnchor(){
		if(!m_atrEx){
			FCAnchor anchor;
			return anchor;
		}
		return m_atrEx->m_anchor;
	}

	void FCView::setAnchor(const FCAnchor& value){
		if(!m_atrEx){
			m_atrEx = new FCAtrEx;
		}
		m_atrEx->m_anchor = value;
	}

	bool FCView::autoEllipsis(){
		if(!m_atrEx){
            return false;
        }
        return m_atrEx->m_autoEllipsis;
	}

	void FCView::setAutoEllipsis(bool value){
		if(!m_atrEx){
            m_atrEx = new FCAtrEx;
        }
        m_atrEx->m_autoEllipsis = value;
	}

	bool FCView::autoSize(){
		if(!m_atrEx){
            return false;
        }
        return m_atrEx->m_autoSize;
	}

	void FCView::setAutoSize(bool value){
		if(!m_atrEx){
            m_atrEx = new FCAtrEx;
        }
        if(m_atrEx->m_autoSize != value){
            m_atrEx->m_autoSize = value;
            onAutoSizeChanged();
        }
	}

	Long FCView::getBackColor(){
		return m_backColor;
	}

	void FCView::setBackColor(Long value){
		if(m_backColor != value){
			m_backColor = value;
			onBackColorChanged();
		}
	}

	String FCView::getBackImage(){
		if(!m_atrEx){
            return L"";
        }
        return m_atrEx->m_backImage;
	}

	void FCView::setBackImage(const String& value){
		if(!m_atrEx){
            m_atrEx = new FCAtrEx;
        }
        if(m_atrEx->m_backImage != value){
            m_atrEx->m_backImage = value;
            onBackImageChanged();
        }
	}

	Long FCView::getBorderColor(){
		return m_borderColor;
	}

	void FCView::setBorderColor(Long value){
		m_borderColor = value;
	}

	int FCView::getBorderWidth(){
		if (!m_atrEx){
            return 1;
        }
        else{
            return m_atrEx->m_borderWidth;
        }
	}

	void FCView::setBorderWidth(int value){
		if (!m_atrEx){
            m_atrEx = new FCAtrEx();
        }
        m_atrEx->m_borderWidth = value;
	}

	int FCView::getBottom(){
		return getTop() + getHeight();
	}

	FCRect FCView::getBounds(){
		FCRect rect = {getLeft(), getTop(), getRight(), getBottom()};
		return rect;
	}

	void FCView::setBounds(const FCRect& value){
		FCPoint location = {value.left, value.top};
		setLocation(location);
		int cx = value.right - value.left;
		int cy = value.bottom - value.top;
		FCSize size = {cx, cy};
		setSize(size);
	}

	void FCView::setBounds2(const FCRect& value){
        if(m_atrEx){
            setBounds(value);
        }else{
            m_location.x = value.left;
            m_location.y = value.top;
            m_size.cx = value.right - value.left;
            m_size.cy = value.bottom - value.top;
        }
    }

	bool FCView::canFocus(){
        if (!m_atrEx)
        {
            return true;
        }
        return m_atrEx->m_canFocus;
    }

    void FCView::setCanFocus(bool value){
        if (!m_atrEx)
        {
            m_atrEx = new FCAtrEx();
        }
        m_atrEx->m_canFocus = value;
    }

	bool FCView::isCapture(){
        if (m_native){
            if (m_native->getHoveredView() == this || m_native->getPushedView() == this){
                return true;
            }
        }
        return false;
	}

	int FCView::getCornerRadius(){
		if(!m_atrEx){
            return 0;
        }
        return m_atrEx->m_cornerRadius;
	}

	void FCView::setCornerRadius(int value){
		if(!m_atrEx){
            m_atrEx = new FCAtrEx;
        }
        m_atrEx->m_cornerRadius = value;
	}

	FCCursors FCView::getCursor(){
		if(!m_atrEx){
            return FCCursors_Arrow;
        }
        return m_atrEx->m_cursor;
	}

	void FCView::setCursor(FCCursors value){
		if(!m_atrEx){
            m_atrEx = new FCAtrEx;
        }
        m_atrEx->m_cursor = value;
	}

	bool FCView::displayOffset(){
		if(!m_atrEx){
            return true;
        }
        return m_atrEx->m_displayOffset;
	}

	void FCView::setDisplayOffset(bool value){
		if(!m_atrEx){
            m_atrEx = new FCAtrEx;
        }
        m_atrEx->m_displayOffset = value;
	}

	FCRect FCView::getDisplayRect(){
		if (m_atrEx && m_atrEx->m_useRegion){
            return m_atrEx->m_region;
        }
		else{
			FCRect displayRect = {0, 0, getWidth(), getHeight()};
			return displayRect;
		}
	}

	FCDockStyle FCView::getDock(){
		if(!m_atrEx){
            return FCDockStyle_None;
        }
        return m_atrEx->m_dock;
	}

	void FCView::setDock(FCDockStyle value){
		if(!m_atrEx){
            m_atrEx = new FCAtrEx;
        }
        if(m_atrEx->m_dock != value){
            m_atrEx->m_dock = value;
            onDockChanged();
        }
	}

	bool FCView::isEnabled(){
		return m_enabled;
	}

	void FCView::setEnabled(bool value){
		if(m_enabled != value){
			m_enabled = value;
			onEnableChanged();
		}
	}

	bool FCView::isFocused(){
        if (m_native){
            if (m_native->getFocusedView() == this){
                return true;
            }
        }
        return false;
	}

	void FCView::setFocused(bool value){
        if (m_native){
            if (value){
                m_native->setFocusedView(this);
            }
            else{
                if (m_native->getFocusedView() == this){
                    m_native->setFocusedView(0);
                }
            }
        }
	}

	FCFont* FCView::getFont(){
		return m_font;
	}

	void FCView::setFont(FCFont *value){
		m_font->copy(value);
		onFontChanged();
	}

	int FCView::getHeight(){
		if(m_atrEx && m_atrEx->m_percentSize && m_atrEx->m_percentSize->cy != -1){
			FCSize parentSize = m_parent ? m_parent->getSize() : m_native->getSize();
			return (int)(parentSize.cy * m_atrEx->m_percentSize->cy);
		}
		else{
			return m_size.cy;
		}
	}

	void FCView::setHeight(int value){
		if(m_atrEx && m_atrEx->m_percentSize && m_atrEx->m_percentSize->cy != -1){
			return;
		}
		else{
			FCSize size = {m_size.cx, value};
			setSize(size);
		}
	}

	bool FCView::isDragging(){
		if(!m_atrEx){
            return false;
        }
        return m_atrEx->m_isDragging;
	}

	bool FCView::isWindow(){
		if(!m_atrEx){
            return false;
        }
        return m_atrEx->m_isWindow;
	}

	void FCView::setWindow(bool value){
		if(!m_atrEx){
            m_atrEx = new FCAtrEx;
        }
        m_atrEx->m_isWindow = value;
	}

	int FCView::getLeft(){
		if(m_atrEx && m_atrEx->m_percentLocation && m_atrEx->m_percentLocation->x != -1){
			FCSize parentSize = m_parent ? m_parent->getSize() : m_native->getSize();
			return (int)(parentSize.cx * m_atrEx->m_percentLocation->x);
		}
		else{
			return m_location.x;
		}
	}

	void FCView::setLeft(int value){
		if(m_atrEx && m_atrEx->m_percentLocation && m_atrEx->m_percentLocation->x != -1){
			return;
		}
		else{
			FCPoint location = {value, m_location.y};
			setLocation(location);
		}
	}

	FCPoint FCView::getLocation(){
		if(m_atrEx && m_atrEx->m_percentLocation){
			FCPoint location = {getLeft(), getTop()};
			return location;
		}
		else{
			return m_location;
		}
	}

	void FCView::setLocation(const FCPoint& value){
		if(value.x != m_location.x || value.y != m_location.y){
			if(m_atrEx && m_atrEx->m_percentLocation){
				if(m_atrEx->m_percentLocation->x != -1){
				}
				else{
					m_location.x = value.x;
				}
				if(m_atrEx->m_percentLocation->y != -1){
				}
				else{
					m_location.y = value.y;
				}
			}
			else{
				m_location = value;
			}
			onLocationChanged();
		}
	}

	FCPadding FCView::getMargin(){
		if(!m_atrEx){
			FCPadding margin(0);
			return margin;
		}
		return m_atrEx->m_margin;
	}

	void FCView::setMargin(const FCPadding& value){
		if(!m_atrEx){
			m_atrEx = new FCAtrEx;
		}
		m_atrEx->m_margin = value;
		onMarginChanged();
	}

	FCSize FCView::getMaximumSize(){
		if(!m_atrEx){
			FCSize size = {100000, 100000};
			return size;
		}
		return m_atrEx->m_maximumSize;
	}

	void FCView::setMaximumSize(FCSize value){
		if(!m_atrEx){
			m_atrEx = new FCAtrEx;
		}
		m_atrEx->m_maximumSize = value;
	}

	FCSize FCView::getMinimumSize(){
		if(!m_atrEx){
			FCSize size = {0, 0};
			return size;
		}
		return m_atrEx->m_minimumSize;
	}

	void FCView::setMinimumSize(FCSize value){
		if(!m_atrEx){
			m_atrEx = new FCAtrEx;
		}
		m_atrEx->m_minimumSize = value;
	}

	FCPoint FCView::getTouchPoint(){
		if(m_native){
			FCPoint mp = m_native->getTouchPoint();
			return pointToView(mp);
		}
		else{
			FCPoint mp = {0};
			return mp;
		}
	}

	String FCView::getName(){
		return m_name;
	}

	void FCView::setName(const String& value){
		m_name = value;
	}

	FCNative* FCView::getNative(){
		return m_native;
	}

	void FCView::setNative(FCNative *value){
		m_native = value;
		int viewsSize = (int)m_views.size();
		for(int i = 0; i < viewsSize; i++){
			m_views.get(i)->setNative(value);
		}
		onLoad();
	}

	float FCView::getOpacity(){
		return m_opacity;
	}

	void FCView::setOpacity(float value){
		m_opacity = value;
	}

	FCPadding FCView::getPadding(){
		if(!m_atrEx){
			FCPadding padding(0);
			return padding;
		}
		return m_atrEx->m_padding;
	}

	void FCView::setPadding(const FCPadding& value){
		if(!m_atrEx){
			m_atrEx = new FCAtrEx;
		}
		m_atrEx->m_padding = value;
		onPaddingChanged();
	}

	FCView* FCView::getParent(){
		return m_parent;
	}

	void FCView::setParent(FCView *value){
		if(m_parent != value){
			m_parent = value;
			onParentChanged();
		}
	}

	FCRect FCView::getRegion(){
		if(!m_atrEx){
			FCRect rect = {0};
			return rect;
		}
		return m_atrEx->m_region;
	}

	void FCView::setRegion(const FCRect& value){
		if(!m_atrEx){
			m_atrEx = new FCAtrEx;
		}
		m_atrEx->m_useRegion = true;
		m_atrEx->m_region = value;
		onRegionChanged();
	}

	int FCView::getRight(){
		return getLeft() + getWidth();
	}

	FCSize FCView::getSize(){
		if(m_atrEx && m_atrEx->m_percentSize){
			FCSize size = {getWidth(), getHeight()};
			return size;
		}
		else{
			return m_size;
		}
	}

	void FCView::setSize(const FCSize& value){
		FCSize newSize = value;
		if (newSize.cx < 0)
        {
            newSize.cx = 0;
        }
        if (newSize.cy < 0)
        {
            newSize.cy = 0;
        }
		if(m_atrEx){
			if (newSize.cx > m_atrEx->m_maximumSize.cx){
				newSize.cx = m_atrEx->m_maximumSize.cx;
			}
			if (newSize.cy > m_atrEx->m_maximumSize.cy){
				newSize.cy = m_atrEx->m_maximumSize.cy;
			}
			if (newSize.cx < m_atrEx->m_minimumSize.cx){
				newSize.cx = m_atrEx->m_minimumSize.cx;
			}
			if (newSize.cy < m_atrEx->m_minimumSize.cy){
				newSize.cy = m_atrEx->m_minimumSize.cy;
			}
		}
		if(newSize.cx != m_size.cx || newSize.cy != m_size.cy){
			if(m_atrEx && m_atrEx->m_percentSize){
				m_oldSize = getSize();
				if(m_atrEx->m_percentSize->cx != -1){
				}
				else{
					m_size.cx = newSize.cx;
				}
				if(m_atrEx->m_percentSize->cy != -1){
				}
				else{
					m_size.cy = newSize.cy;
				}
			}
			else{
				m_oldSize = m_size;
				m_size = newSize;
			}
			onSizeChanged();
			update();
		}
	}

	int FCView::getTabIndex(){
		if(!m_atrEx){
            return 0;
        }
        return m_atrEx->m_tabIndex;
	}

	void FCView::setTabIndex(int value){
		if(!m_atrEx){
            m_atrEx = new FCAtrEx;
        }
        if(m_atrEx->m_tabIndex != value){
            m_atrEx->m_tabIndex = value;
            onTabIndexChanged();
        }
	}

	bool FCView::isTabStop(){
		if(!m_atrEx){
            return false;
        }
        return m_atrEx->m_tabStop;
	}

	void FCView::setTabStop(bool value){
		if(!m_atrEx){
            m_atrEx = new FCAtrEx;
        }
        if(m_atrEx->m_tabStop != value){
            m_atrEx->m_tabStop = value;
            onTabStopChanged();
        }
	}

	Object FCView::getTag(){
		if(!m_atrEx){
            return 0;
        }
        return m_atrEx->m_tag;
	}

	void FCView::setTag(Object value){
		if(!m_atrEx){
            m_atrEx = new FCAtrEx;
        }
        m_atrEx->m_tag = value;
	}

	String FCView::getText(){
		return m_text;
	}

	void FCView::setText(const String& value){
		if(m_text != value){
			m_text = value;
			onTextChanged();
		}
	}

	Long FCView::getTextColor(){
		return m_textColor;
	}

	void FCView::setTextColor(Long value){
		if(m_textColor != value){
			m_textColor = value;
			onTextColorChanged();
		}
	}

	int FCView::getTop(){
		if(m_atrEx && m_atrEx->m_percentLocation && m_atrEx->m_percentLocation->y != -1){
			FCSize parentSize = m_parent ? m_parent->getSize() : m_native->getSize();
			return (int)(parentSize.cy * m_atrEx->m_percentLocation->y);
		}
		else{
			return m_location.y;
		}
	}

	void FCView::setTop(int value){
		if(m_atrEx && m_atrEx->m_percentLocation && m_atrEx->m_percentLocation->y != -1){
			return;
		}
		else{
			FCPoint location = {m_location.x, value};
			setLocation(location);
		}
	}

	bool FCView::isTopMost(){
		return m_topMost;
	}

	void FCView::setTopMost(bool value){
		m_topMost = value;
	}

	bool FCView::useRegion(){
		if(!m_atrEx){
			return false;
		}
		return m_atrEx->m_useRegion;
	}

	FCVerticalAlign FCView::getVerticalAlign(){
		return m_verticalAlign;
	}

	void FCView::setVerticalAlign(FCVerticalAlign value){
		m_verticalAlign = value;
	}

	bool FCView::isVisible(){
		return m_visible;
	}

	void FCView::setVisible(bool value){
		if(m_visible != value){
			m_visible = value;
			onVisibleChanged();
		}
	}

	int FCView::getWidth(){
		if(m_atrEx && m_atrEx->m_percentSize && m_atrEx->m_percentSize->cx != -1){
			FCSize parentSize = m_parent ? m_parent->getSize() : m_native->getSize();
			return (int)(parentSize.cx * m_atrEx->m_percentSize->cx);
		}
		else{
			return m_size.cx;
		}
	}

	void FCView::setWidth(int value){
		if(m_atrEx && m_atrEx->m_percentSize && m_atrEx->m_percentSize->cx != -1){
			return;
		}
		else{
			FCSize size = {value, m_size.cy};
			setSize(size);
		}
	}

	/////////////////////////////////////////////////////////////////////////////////////////////////////////////

	void FCView::addView(FCView *view){
		view->setParent(this);
		view->setNative(m_native);
		m_views.add(view);
		view->onAdd();
	}

	void FCView::addEvent(Object func, const String& eventName, Object pInvoke){
		if(!m_atrEx){
			m_atrEx = new FCAtrEx;
		}
		ArrayList<Object> *events = 0;
        ArrayList<Object> *invokes = 0;
        if(m_atrEx->m_events.containsKey(eventName)){
            events = m_atrEx->m_events.get(eventName);
            invokes = m_atrEx->m_invokes.get(eventName);
		}
		else{
			events = new ArrayList<Object>;
            m_atrEx->m_events.put(eventName, events);
            invokes = new ArrayList<Object>;
            m_atrEx->m_invokes.put(eventName, invokes);
		}
		events->add(func);
        invokes->add(pInvoke);
	}

	void FCView::beginInvoke(Object args){
		if (m_native){
            FCHost *host = m_native->getHost();
            host->beginInvoke(this, args);
        }
	}

	void FCView::bringChildToFront(FCView *childView){
		if(m_views.size() > 0){
			for(int c = 0; c < m_views.size(); c++){
				if(m_views.get(c) == childView){
					m_views.removeAt(c);
					break;
				}
			}
			m_views.add(childView);
		}
	}

	void FCView::bringToFront(){
		if(m_native){
			m_native->bringToFront(this);
		}
	}

	void FCView::clearViews(){
		while((int)m_views.size() > 0){
            FCView *view = m_views.get(0);
            m_views.removeAt(0);
            view->onRemove();
            delete view;
        }
	}

	bool FCView::containsView(FCView *view){
		if(m_views.size() > 0){
			for(int c = 0; c < m_views.size(); c++){
				if(m_views.get(c) == view){
					return true;
				}
			}
		}
		return false;
	}

	bool FCView::containsPoint(const FCPoint& mp){
	    FCPoint cPoint = pointToView(mp);
		FCSize size = getSize();
        if (cPoint.x >= 0 && cPoint.x <= size.cx && cPoint.y >= 0 && cPoint.y <= size.cy){
			if (m_atrEx && m_atrEx->m_useRegion){
                if (cPoint.x >= m_atrEx->m_region.left && cPoint.x <= m_atrEx->m_region.right
                    && cPoint.y >= m_atrEx->m_region.top && cPoint.y <= m_atrEx->m_region.bottom){
                    return true;
                }
            }
            else{
                return true;
            }
        }
        return false;
	}

	void FCView::focus(){
		setFocused(true);
	}

	ArrayList<FCView*> FCView::getViews(){
		return m_views;
	}

	String FCView::getViewType(){
		return L"FCView";
	}

	FCPoint FCView::getDisplayOffset(){
		FCPoint offset = {0, 0};
		return offset;
	}

	static int m_timerID = 0;

	int FCView::getNewTimerID(){
		return m_timerID++;
	}

	String FCView::getAttribute(const String& name){
		String value, type;
        getAttribute(name, &value, &type);
        return value;
	}

	void FCView::getAttribute(const String& name, String *value, String *type){
		int len = (int)name.length();
        switch (len){
			case 1:{
					if (name == L"x"){
						*type = L"float";
						if(m_atrEx && m_atrEx->m_percentLocation && m_atrEx->m_percentLocation->x != -1){
							*value = String(L"%") + FCTran::floatToStr(100 * m_atrEx->m_percentLocation->x);
						}
						else{
							*value = FCTran::intToStr(getLeft());
						}
					}
				    else if (name == L"y"){
						*type = L"float";
						if(m_atrEx && m_atrEx->m_percentLocation && m_atrEx->m_percentLocation->y != -1){
							*value = String(L"%") + FCTran::floatToStr(100 * m_atrEx->m_percentLocation->y);
						}
						else{
							*value = FCTran::intToStr(getTop());
						}
                    }
					break;
				   }
			case 2:{
					if(name == L"id"){
						*type = L"text";
						*value = getName();
					}
					break;
				}
            case 3:{
                    if (name == L"top"){
						*type = L"float";
						if(m_atrEx && m_atrEx->m_percentLocation && m_atrEx->m_percentLocation->y != -1){
							*value = String(L"%") + FCTran::floatToStr(100 * m_atrEx->m_percentLocation->y);
						}
						else{
							*value = FCTran::intToStr(getTop());
						}
                    }
                    break;
                }
            case 4:{
                    if (name == L"dock"){
						*type = L"enum:FCDockStyle";
						*value = FCTran::dockToStr(getDock());
                    }
                    else if (name == L"font"){
						*type = L"font";
						*value = FCTran::fontToStr(getFont());
                    }
                    else if (name == L"left"){
						*type = L"float";
						if(m_atrEx && m_atrEx->m_percentLocation && m_atrEx->m_percentLocation->x != -1){
							*value = String(L"%") + FCTran::floatToStr(100 * m_atrEx->m_percentLocation->x);
						}
						else{
							*value = FCTran::intToStr(getLeft());
						}
                    }
                    else if (name == L"name"){
						*type = L"text";
						*value = getName();
                    }
                    else if (name == L"size"){
						*type = L"size";
						if (m_atrEx && m_atrEx->m_percentSize){
                            String pWidth, pHeight, pType;
                            getAttribute(L"width", &pWidth, &pType);
                            getAttribute(L"height", &pHeight, &pType);
                    *value = pWidth + String(L",") + pHeight;
                        }
                        else{
							*value = FCTran::sizeToStr(getSize());
                        }
                    }
                    else if (name == L"text"){
						*type = L"text";
						*value = getText();
                    }
                    break;
                }
            case 5:{
				    if (name == L"align"){
                *type = L"enum:FCHorizontalAlign";
						*value = FCTran::horizontalAlignToStr(getAlign());
                    }
					else if(name == L"value"){
						*type = L"text";
						*value = getText();
					}
                    else if (name == L"width"){
						*type = L"float";
						if(m_atrEx && m_atrEx->m_percentSize && m_atrEx->m_percentSize->cx != -1){
							*value = String(L"%") + FCTran::floatToStr(100 * m_atrEx->m_percentSize->cx);
						}
						else{
							*value = FCTran::intToStr(getWidth());
						}
                    }
                    break;
                }
            case 6:{
                    if (name == L"anchor"){
						*type = L"anchor";
						*value = FCTran::anchorToStr(getAnchor());
                    }
                    else if (name == L"bounds"){
						*type = L"rect";
						*value = FCTran::rectToStr(getBounds());
                    }
                    else if (name == L"cursor"){
						*type = L"enum:FCCursors";
						*value = FCTran::cursorToStr(getCursor());
                    }
                    else if (name == L"height"){
						*type = L"float";
						if(m_atrEx && m_atrEx->m_percentSize && m_atrEx->m_percentSize->cy != -1){
							*value = String(L"%") + FCTran::floatToStr(100 * m_atrEx->m_percentSize->cy);
						}
						else{
							*value = FCTran::intToStr(getHeight());
						}
                    }
                    else if (name == L"margin"){
						*type = L"padding";
						*value = FCTran::paddingToStr(getMargin());
                    }
                    else if (name == L"region"){
						*type = L"rect";
						*value = FCTran::rectToStr(getRegion());
                    }
                    break;
                }
            case 7:{
					if (name == L"enabled"){
						*type = L"bool";
						*value = FCTran::boolToStr(isEnabled());
                    }
                    else if (name == L"focused"){
						*type = L"bool";
						*value = FCTran::boolToStr(isFocused());
                    }
                    else if (name == L"opacity"){
						*type = L"float";
						*value = FCTran::floatToStr(getOpacity());
                    }
                    else if (name == L"padding"){
						*type = L"padding";
						*value = FCTran::paddingToStr(getPadding());
                    }
                    else if (name == L"tabstop"){
						*type = L"bool";
						*value = FCTran::boolToStr(isTabStop());
                    }
                    else if (name == L"topmost"){
						*type = L"bool";
						*value = FCTran::boolToStr(isTopMost());
                    }
                    else if (name == L"visible"){
						*type = L"bool";
						*value = FCTran::boolToStr(isVisible());
                    }
                    break;
                }
            case 8:{
                    if (name == L"autosize"){
						*type = L"bool";
						*value = FCTran::boolToStr(autoSize());
                    }
                    else if (name == L"iswindow"){
						*type = L"bool";
						*value = FCTran::boolToStr(isWindow());
                    }
                    else if (name == L"location"){
						*type = L"point";
						if (m_atrEx && m_atrEx->m_percentLocation){
                            String pLeft, pTop, pType;
                            getAttribute(L"left", &pLeft, &pType);
                            getAttribute(L"top", &pTop, &pType);
                    *value = pLeft + String(L",") + pTop;
                        }
                        else{
							*value = FCTran::pointToStr(getLocation());
                        }             
                    }
                    else if (name == L"tabindex"){
						*type = L"int";
						*value = FCTran::intToStr(getTabIndex());
                    }
					else if (name == L"canfocus"){
						*type = L"bool";
						*value = FCTran::boolToStr(canFocus());
					}
                    break;
                }
            case 9:{
                    if (name == L"allowdrag"){
						*type = L"bool";
						*value = FCTran::boolToStr(allowDrag());
                    }
                    else if (name == L"backcolor"){
						*type = L"color";
						*value = FCTran::colorToStr(getBackColor());
                    }
                    else if (name == L"backimage"){
						*type = L"text";
						*value = getBackImage();
                    }
                    else if (name == L"textcolor"){
						*type = L"color";
						*value = FCTran::colorToStr(getTextColor());
                    }
                    break;
                }
            default:{
					if (name == L"allowpreviewsevent"){
                *type = L"bool";
						*value = FCTran::boolToStr(allowPreviewsEvent());
                    }
                    else if (name == L"autoellipsis"){
						*type = L"bool";
						*value = FCTran::boolToStr(autoEllipsis());
                    }
                    else if (name == L"bordercolor"){
						*type = L"color";
						*value = FCTran::colorToStr(getBorderColor());
                    }
					else if(name == L"cornerradius"){
						*type = L"int";
						*value = FCTran::intToStr(getCornerRadius());
					}
                    else if (name == L"displayoffset"){
						*type = L"bool";
						*value = FCTran::boolToStr(displayOffset());
                    }
                    else if (name == L"maximumsize"){
						*type = L"size";
						*value = FCTran::sizeToStr(getMaximumSize());
                    }
                    else if (name == L"minimumsize"){
						*type = L"size";
						*value = FCTran::sizeToStr(getMinimumSize());
                    }
				    else if (name == L"vertical-align"){
						*type = L"enum:FCVerticalAlign";
						*value = FCTran::verticalAlignToStr(getVerticalAlign());
                    }
					else if (name == L"borderwidth")
                    {
                        *type = L"int";
						*value = FCTran::intToStr(getBorderWidth());
                    }
                    break;
                }
        }
	}

	ArrayList<String> FCView::getEventNames(){
        ArrayList<String> eventNames;
        eventNames.add(L"Add");
        eventNames.add(L"BackColorChanged");
        eventNames.add(L"BackImageChanged");
        eventNames.add(L"Char");
        eventNames.add(L"Click");
        eventNames.add(L"Copy");
        eventNames.add(L"Cut");
        eventNames.add(L"DockChanged");
        eventNames.add(L"DoubleClick");
        eventNames.add(L"DragBegin");
        eventNames.add(L"DragEnd");
        eventNames.add(L"Dragging");
        eventNames.add(L"EnableChanged");
        eventNames.add(L"FontChanged");
        eventNames.add(L"GotFocus");
        eventNames.add(L"Invoke");
        eventNames.add(L"KeyDown");
        eventNames.add(L"KeyUp");
        eventNames.add(L"Load");
        eventNames.add(L"LostFocus");
        eventNames.add(L"MarginChanged");
        eventNames.add(L"TouchDown");
        eventNames.add(L"TouchEnter");
        eventNames.add(L"TouchLeave");
        eventNames.add(L"TouchMove");
        eventNames.add(L"TouchUp");
        eventNames.add(L"TouchWheel");
        eventNames.add(L"PaddingChanged");
        eventNames.add(L"ParentChanged");
        eventNames.add(L"Paint");
        eventNames.add(L"PaintBorder");
        eventNames.add(L"Paste");
        eventNames.add(L"RegionChanged");
        eventNames.add(L"Remove");
        eventNames.add(L"SizeChanged");
        eventNames.add(L"TabIndexChanged");
        eventNames.add(L"TabStop");
        eventNames.add(L"TabStopChanged");
        eventNames.add(L"TextChanged");
        eventNames.add(L"TextColorChanged");
        eventNames.add(L"Timer");
        eventNames.add(L"VisibleChanged");
        return eventNames;
    }

	ArrayList<String> FCView::getAttributeNames(){
		ArrayList<String> attributeNames;
		attributeNames.add(L"Align");
		attributeNames.add(L"AllowDrag");
		attributeNames.add(L"AllowPreviewsEvent");
		attributeNames.add(L"Anchor");
		attributeNames.add(L"AutoEllipsis");
		attributeNames.add(L"AutoSize");
		attributeNames.add(L"BackColor");
		attributeNames.add(L"BackImage");
		attributeNames.add(L"BorderColor");
		attributeNames.add(L"BorderWidth");
		attributeNames.add(L"Bounds");
		attributeNames.add(L"CanFocus");
		attributeNames.add(L"CornerRadius");
		attributeNames.add(L"Cursor");
		attributeNames.add(L"DisplayOffset");
		attributeNames.add(L"Dock");
		attributeNames.add(L"Enabled");
		attributeNames.add(L"Focused");
		attributeNames.add(L"Font");
		attributeNames.add(L"Height");
		attributeNames.add(L"IsWindow");
		attributeNames.add(L"Left");
		attributeNames.add(L"Location");
		attributeNames.add(L"Margin");
		attributeNames.add(L"MaximumSize");
		attributeNames.add(L"MinimumSize");
		attributeNames.add(L"Name");
		attributeNames.add(L"Opacity");
		attributeNames.add(L"Padding");
		attributeNames.add(L"Region");
		attributeNames.add(L"Size");
		attributeNames.add(L"TabIndex");
		attributeNames.add(L"TabStop");
		attributeNames.add(L"Text");
		attributeNames.add(L"TextColor");
		attributeNames.add(L"Top");
		attributeNames.add(L"TopMost");
		attributeNames.add(L"Value");
		attributeNames.add(L"Vertical-Align");
		attributeNames.add(L"Visible");
		attributeNames.add(L"Width");
		attributeNames.add(L"X");
		attributeNames.add(L"Y");
        return attributeNames;
	}

	bool FCView::hasChildren(){
		return m_views.size() > 0;
	}

	void FCView::hide(){
		setVisible(false);
	}

	void FCView::insertView(int index, FCView *view){
		view->setParent(this);
        view->setNative(m_native);
        m_views.insert(index, view);
        view->onAdd();
	}

	void FCView::invalidate(){
		if(m_native){
			if(isPaintVisible(this)){
				m_native->invalidate(this);
			}
		}
	}

	void FCView::invoke(Object args){
		if (m_native){
            FCHost *host = m_native->getHost();
            host->invoke(this, args);
        }
	}

	bool FCView::isPaintEnabled(FCView *view){
	    if (view->isEnabled()){
            FCView *parent = view->getParent();
            if (parent){
                return isPaintEnabled(parent);
            }
            else{
                return true;
            }
        }
        else{
            return false;
        }
	}

	bool FCView::isPaintVisible(FCView *view){
		if (view->isVisible()){
            FCView *parent = view->getParent();
            if (parent){
                return isPaintVisible(parent);
            }
            else{
                return true;
            }
        }
        else{
            return false;
        }
	}

	void FCView::onAdd(){
		callEvents(L"onadd");
	}

	void FCView::onAutoSizeChanged(){
		callEvents(L"onautosizechanged");
    }

	void FCView::onBackColorChanged(){
		callEvents(L"onbackcolorchanged");
    }

	void FCView::onBackImageChanged(){
		callEvents(L"onbackimagechanged");
    }

	void FCView::onChar(wchar_t ch){
	}

	void FCView::onClick(FCTouchInfo touchInfo){
		callTouchEvents(L"onclick", touchInfo);
	}

	void FCView::onCopy(){
		callEvents(L"oncopy");
	}

	void FCView::onCut(){
		callEvents(L"oncut");
	}

	void FCView::onDockChanged(){
		callEvents(L"ondockchanged");
    }

	void FCView::onDoubleClick(FCTouchInfo touchInfo){
		callTouchEvents(L"ondoubleclick", touchInfo);
	}

	bool FCView::onDragBegin(){
		if(!m_atrEx){
            m_atrEx = new FCAtrEx;
        }
		m_atrEx->m_isDragging = true;
		callEvents(L"ondragbegin");
		return true;
	}

	void FCView::onDragEnd(){
		if(!m_atrEx){
            m_atrEx = new FCAtrEx;
        }
		m_atrEx->m_isDragging = false;
		callEvents(L"ondragend");
	}

	void FCView::onDragging(){
		if(!m_atrEx){
            m_atrEx = new FCAtrEx;
        }
		m_atrEx->m_isDragging = true;
		callEvents(L"ondragging");
	}

	void FCView::onDragInFiles(ArrayList<String> *files){
        
    }

	void FCView::onDragReady(FCPoint *startOffset){
		startOffset->x = 5;
		startOffset->y = 5;
	}

	void FCView::onEnableChanged(){
		callEvents(L"onenablechanged");
	}

	void FCView::onFontChanged(){
		callEvents(L"onfontchanged");
    }

	void FCView::onGotFocus(){
		callEvents(L"ongotfocus");
	}

	void FCView::onInvoke(Object args){
		callInvokeEvents(L"oninvoke", args);
	}

	void FCView::onLoad(){
		callEvents(L"onload");
	}

	void FCView::onLocationChanged(){
		callEvents(L"onlocationchanged");
	}

	void FCView::onLostFocus(){
		callEvents(L"onlostfocus");
	}

	void FCView::onKeyDown(char key){
		callKeyEvents(L"onkeydown", key);
		FCHost *host = getNative()->getHost();
		if (host->isKeyPress(VK_CONTROL)){
			if (key == 67){
				onCopy();
			}
			else if (key == 86){
				onPaste();
			}
			else if(key == 88){
				onCut();
			}
		}
	}

	void FCView::onKeyUp(char key){
		callKeyEvents(L"onkeyup", key);
	}

	void FCView::onMarginChanged(){
		callEvents(L"onmarginchanged");
    }

	void FCView::onTouchDown(FCTouchInfo touchInfo){
		callTouchEvents(L"ontouchdown", touchInfo);
	}

	void FCView::onTouchEnter(FCTouchInfo touchInfo){
		callTouchEvents(L"ontouchenter", touchInfo);
		if (autoEllipsis()){
            if ((int)m_text.length() > 0){
                m_native->getHost()->showToolTip(m_text, m_native->getTouchPoint());
            }
        }
	}

	void FCView::onTouchLeave(FCTouchInfo touchInfo){
		callTouchEvents(L"ontouchleave", touchInfo);
	}

	void FCView::onTouchMove(FCTouchInfo touchInfo){
		callTouchEvents(L"ontouchmove", touchInfo);
	}

	void FCView::onTouchUp(FCTouchInfo touchInfo){
		callTouchEvents(L"ontouchup", touchInfo);
	}

	void FCView::onTouchWheel(FCTouchInfo touchInfo){
		callTouchEvents(L"ontouchwheel", touchInfo);
	}

	void FCView::onPaddingChanged(){
		callEvents(L"onpaddingchanged");
    }

	void FCView::onPaint(FCPaint *paint, const FCRect& clipRect){
		onPaintBackground(paint, clipRect);
		onPaintForeground(paint, clipRect);
		callPaintEvents(L"onpaint", paint, clipRect);
	}

	void FCView::onPaintBackground(FCPaint *paint, const FCRect& clipRect){
		FCRect rect = {0, 0, getWidth(), getHeight()};
		paint->fillRoundRect(getPaintingBackColor(), rect, getCornerRadius());
		String bkImage = getPaintingBackImage();
		if ((int)bkImage.length() > 0){
			paint->drawImage(bkImage.c_str(), rect);
		}
	}

	void FCView::onPaintBorder(FCPaint *paint, const FCRect& clipRect){
		FCRect borderRect = {0, 0, getWidth(), getHeight()};
		paint->drawRoundRect(getPaintingBorderColor(), getBorderWidth(), 0, borderRect, getCornerRadius());
		callPaintEvents(L"onpaintborder", paint, clipRect);
	}

	void FCView::onPaintForeground(FCPaint *paint, const FCRect& clipRect){
	}

	void FCView::onParentChanged(){
		callEvents(L"onparentchanged");
    }

	void FCView::onPaste(){
		callEvents(L"onpaste");
	}

	bool FCView::onPrePaint(FCPaint *paint, const FCRect& clipRect){
		return callPaintEvents(L"onprepaint", paint, clipRect);
	}

	bool FCView::onPreviewsKeyEvent(String eventName, char key){
		return callPreviewsKeyEvent(L"onpreviewskeyevent", eventName, key);
	}

	bool FCView::onPreviewsTouchEvent(String eventName, FCTouchInfo touchInfo){
		return callPreviewsTouchEvent(L"onpreviewstouchevent", eventName, touchInfo);
	}

	void FCView::onRegionChanged(){
		callEvents(L"onregionchanged");
    }

	void FCView::onRemove(){
		callEvents(L"onremove");
	}

    void FCView::onScaling(double scaleFactorX, double scaleFactorY) {
        m_location.x = (int)(m_location.x * scaleFactorX);
		m_location.y = (int)(m_location.y * scaleFactorY);
        m_size.cx = (int)(m_size.cx * scaleFactorX);
		m_size.cy = (int)(m_size.cy * scaleFactorY);
        m_font->m_fontSize = (float)(m_font->m_fontSize * (scaleFactorX + scaleFactorY) / 2);
		if(m_atrEx){
			m_atrEx->m_maximumSize.cx = (int)(m_atrEx->m_maximumSize.cx * scaleFactorX);
			m_atrEx->m_maximumSize.cy = (int)(m_atrEx->m_maximumSize.cy * scaleFactorY);
			m_atrEx->m_minimumSize.cx = (int)(m_atrEx->m_minimumSize.cx * scaleFactorX);
			m_atrEx->m_minimumSize.cy = (int)(m_atrEx->m_minimumSize.cy * scaleFactorY);
		}
        int viewSize = m_views.size();
        for (int i = 0; i < viewSize; i++) {
            m_views.get(i)->onScaling(scaleFactorX, scaleFactorY);
        }
    }

	void FCView::onSizeChanged(){
		callEvents(L"onsizechanged");
		update();
	}

	void FCView::onTabIndexChanged(){
		callEvents(L"ontabindexchanged");
    }

	void FCView::onTabStop(){
		callEvents(L"ontabstop");
	}

	void FCView::onTabStopChanged(){
		callEvents(L"ontabstopchanged");
    }

	void FCView::onTextChanged(){
		callEvents(L"ontextchanged");
	}

	void FCView::onTextColorChanged(){
		callEvents(L"ontextcolorchanged");
    }

	void FCView::onTimer(int timerID){
		callTimerEvents(L"ontimer", timerID);
	}

	void FCView::onVisibleChanged(){
		callEvents(L"onvisiblechanged");
	}

	FCPoint FCView::pointToView(const FCPoint& mp){
	    if (m_native){
            int clientX = m_native->clientX(this);
            int clientY = m_native->clientY(this);
			FCPoint point = {mp.x - clientX, mp.y - clientY};
			return point;
        }
        else{
            return mp;
        }
	}

	FCPoint FCView::pointToNative(const FCPoint& mp){
		if (m_native){
            int clientX = m_native->clientX(this);
            int clientY = m_native->clientY(this);
			FCPoint point = {mp.x + clientX, mp.y + clientY};
			return point;
        }
        else{
            return mp;
        }
	}

	void FCView::removeView(FCView *view){
		if(m_native){
			m_native->clearViewState(view);
		}
		for(int c = 0; c < m_views.size(); c++){
			FCView *baseView = m_views.get(c);
			if(baseView == view){
				baseView->onRemove();
				m_views.removeAt(c);
				view->setParent(0);
				return;
			}
		}
	}

	void FCView::removeEvent(Object func, const String& eventName){
		if(m_atrEx){
			if(m_atrEx->m_events.containsKey(eventName)){
                ArrayList<Object> *events = m_atrEx->m_events.get(eventName);
				int eventSize = (int)events->size();
				int removeIndex = -1;
				for(int i = 0; i < eventSize; i++){
					if(events->get(i) == func){
						removeIndex = i;
						break;
					}
				}
				if(removeIndex >= 0){
					ArrayList<Object> *invokes = m_atrEx->m_invokes.get(eventName);
                    for(int i = 0; i < eventSize; i++) {
                        if (i == removeIndex) {
                            events->removeAt(i);
							break;
						}
					}
					for(int i = 0; i < eventSize; i++){
                        if(i == removeIndex){
                            invokes->removeAt(i);
							break;
						}
					}
				}
			}
		}
	}

	void FCView::sendChildToBack(FCView *childView){
		if(m_views.size() > 0){
			for(int c = 0; c < m_views.size(); c++){
				if(m_views.get(c) ==  childView){
					m_views.removeAt(c);
					break;
				}
			}
			m_views.insert(0, childView);
		}
	}

	void FCView::setAttribute(const String& name, const String& value){
		int len = (int)name.length();
        switch (len){
			case 1:{
					if (name == L"x"){
						if(value.find(L"%") != -1){
							if(!m_atrEx){
								m_atrEx = new FCAtrEx;
							}
							float percentValue = FCTran::strToFloat(FCTran::replace(value, L"%", L"")) / 100;
							if(!m_atrEx->m_percentLocation){
								m_atrEx->m_percentLocation = new FCPointF();
								m_atrEx->m_percentLocation->y = -1;
							}
							m_atrEx->m_percentLocation->x = percentValue;
						}
						else{
							if(m_atrEx && m_atrEx->m_percentLocation){
								m_atrEx->m_percentLocation->x = -1;
							}
							setLeft(FCTran::strToInt(value));
						}
					}else if (name == L"y"){
						if(value.find(L"%") != -1){
							if(!m_atrEx){
								m_atrEx = new FCAtrEx;
							}
							float percentValue = FCTran::strToFloat(FCTran::replace(value, L"%", L"")) / 100;
							if(!m_atrEx->m_percentLocation){
								m_atrEx->m_percentLocation = new FCPointF();
								m_atrEx->m_percentLocation->x = -1;
							}
							m_atrEx->m_percentLocation->y = percentValue;
						}
						else{
							if(m_atrEx && m_atrEx->m_percentLocation){
								m_atrEx->m_percentLocation->y = -1;
							}
							setTop(FCTran::strToInt(value));
						}
					}
					break;
				   }
			case 2:{
					if(name == L"id"){
						setName(value);
					}
					break;
				}
            case 3:{
                    if (name == L"top"){
						if(value.find(L"%") != -1){
							if(!m_atrEx){
								m_atrEx = new FCAtrEx;
							}
							float percentValue = FCTran::strToFloat(FCTran::replace(value, L"%", L"")) / 100;
							if(!m_atrEx->m_percentLocation){
								m_atrEx->m_percentLocation = new FCPointF();
								m_atrEx->m_percentLocation->x = -1;
							}
							m_atrEx->m_percentLocation->y = percentValue;
						}
						else{
							if(m_atrEx && m_atrEx->m_percentLocation){
								m_atrEx->m_percentLocation->y = -1;
							}
							setTop(FCTran::strToInt(value));
						}
                    }
                    break;
                }
            case 4:{
                    if (name == L"dock"){
						setDock(FCTran::strToDock(value));
                    }
                    else if (name == L"font"){
						FCFont tFont = FCTran::strToFont(value);
						setFont(&tFont);
                    }
                    else if (name == L"left"){
						if(value.find(L"%") != -1){
							if(!m_atrEx){
								m_atrEx = new FCAtrEx;
							}
							float percentValue = FCTran::strToFloat(FCTran::replace(value, L"%", L"")) / 100;
							if(!m_atrEx->m_percentLocation){
								m_atrEx->m_percentLocation = new FCPointF();
								m_atrEx->m_percentLocation->y = -1;
							}
							m_atrEx->m_percentLocation->x = percentValue;
						}
						else{
							if(m_atrEx && m_atrEx->m_percentLocation){
								m_atrEx->m_percentLocation->x = -1;
							}
							setLeft(FCTran::strToInt(value));
						}
                    }
                    else if (name == L"name"){
						setName(value);
                    }
                    else if (name == L"size"){
						if ((int)value.find(L"%") == -1)
                    {
                        setSize(FCTran::strToSize(value));
                    }
                    else
                    {
                        ArrayList<String> strs = FCTran::split(value, L",");
                        setAttribute(L"width", strs.get(0));
                        setAttribute(L"height", strs.get(1));
                    }
                    }
                    else if (name == L"text"){
						setText(value);
                    }
                    break;
                }
            case 5:{
				    if (name == L"align"){
						setAlign(FCTran::strToHorizontalAlign(value));
                    }
					else if(name == L"value"){
						setText(value);
					}
                    else if (name == L"width"){
						if(value.find(L"%") != -1){
							if(!m_atrEx){
								m_atrEx = new FCAtrEx;
							}
							float percentValue = FCTran::strToFloat(FCTran::replace(value, L"%", L"")) / 100;
							if(!m_atrEx->m_percentSize){
								m_atrEx->m_percentSize = new FCSizeF();
								m_atrEx->m_percentSize->cy = -1;
							}
							m_atrEx->m_percentSize->cx = percentValue;
						}
						else{
							if(m_atrEx && m_atrEx->m_percentSize){
								m_atrEx->m_percentSize->cx = -1;
							}
							setWidth(FCTran::strToInt(value));
						}
                    }
                    break;
                }
            case 6:{
                    if (name == L"anchor"){
						setAnchor(FCTran::strToAnchor(value));
                    }
                    else if (name == L"bounds"){
						setBounds(FCTran::strToRect(value));
                    }
                    else if (name == L"cursor"){
						setCursor(FCTran::strToCursor(value));
                    }
                    else if (name == L"height"){
						if(value.find(L"%") != -1){
							if(!m_atrEx){
								m_atrEx = new FCAtrEx;
							}
							float percentValue = FCTran::strToFloat(FCTran::replace(value, L"%", L"")) / 100;
							if(!m_atrEx->m_percentSize){
								m_atrEx->m_percentSize = new FCSizeF();
								m_atrEx->m_percentSize->cx = -1;
							}
							m_atrEx->m_percentSize->cy = percentValue;
						}
						else{
							if(m_atrEx && m_atrEx->m_percentSize){
								m_atrEx->m_percentSize->cy = -1;
							}
							setHeight(FCTran::strToInt(value));
						}
                    }
                    else if (name == L"margin"){
						setMargin(FCTran::strToPadding(value));
                    }
                    else if (name == L"region"){
						setRegion(FCTran::strToRect(value));
                    }
                    break;
                }
            case 7:{
                    if (name == L"enabled"){
						setEnabled(FCTran::strToBool(value));
                    }
                    else if (name == L"focused"){
						setFocused(FCTran::strToBool(value));
                    }
                    else if (name == L"opacity"){
						setOpacity(FCTran::strToFloat(value));
                    }
                    else if (name == L"padding"){
						setPadding(FCTran::strToPadding(value));
                    }
                    else if (name == L"tabstop"){
						setTabStop(FCTran::strToBool(value));
                    }
                    else if (name == L"topmost"){
						setTopMost(FCTran::strToBool(value));
                    }
                    else if (name == L"visible"){
						setVisible(FCTran::strToBool(value));
                    }
                    break;
                }
            case 8:{
                    if (name == L"autosize"){
						setAutoSize(FCTran::strToBool(value));
                    }
                    else if (name == L"iswindow"){
						setWindow(FCTran::strToBool(value));
                    }
                    else if (name == L"location"){
						if ((int)value.find(L"%") == -1)
						{
							setLocation(FCTran::strToPoint(value));
						}
						else
						{
							ArrayList<String> strs = FCTran::split(value, L",");
							setAttribute(L"left", strs.get(0));
							setAttribute(L"top", strs.get(1));
						}
                    }
                    else if (name == L"tabindex"){
						setTabIndex(FCTran::strToInt(value));
                    }
					else if (name == L"canfocus"){
						setCanFocus(FCTran::strToBool(value));
					}
                    break;
                }
            case 9:{
                    if (name == L"allowdrag"){
						setAllowDrag(FCTran::strToBool(value));
                    }
                    else if (name == L"backcolor"){
						setBackColor(FCTran::strToColor(value));
                    }
                    else if (name == L"backimage"){
						setBackImage(value);
                    }
                    else if (name == L"textcolor"){
						setTextColor(FCTran::strToColor(value));
                    }
                    break;
                }
            default:{
					if (name == L"allowpreviewsevent"){
						setAllowPreviewsEvent(FCTran::strToBool(value));
					}
                    else if (name == L"autoellipsis"){
						setAutoEllipsis(FCTran::strToBool(value));
                    }
                    else if (name == L"bordercolor"){
						setBorderColor(FCTran::strToColor(value));
                    }
					else if(name == L"cornerradius"){
						setCornerRadius(FCTran::strToInt(value));
					}
                    else if (name == L"displayoffset"){
						setDisplayOffset(FCTran::strToBool(value));
                    }
                    else if (name == L"maximumsize"){
						setMaximumSize(FCTran::strToSize(value));
                    }
                    else if (name == L"minimumsize"){
						setMinimumSize(FCTran::strToSize(value));
                    }
				    else if (name == L"vertical-align"){
						setVerticalAlign(FCTran::strToVerticalAlign(value));
                    }else if (name == L"borderwidth"){
						setBorderWidth(FCTran::strToInt(value));
                    }
                    break;
                }
        }
	}

	void FCView::sendToBack(){
		if(m_native){
			m_native->sendToBack(this);
		}
	}

	void FCView::show(){
		setVisible(true);
	}

	void FCView::startTimer(int timerID, int interval){
		if(m_native){
			m_native->startTimer(this, timerID, interval);
		}
	}

	void FCView::stopTimer(int timerID){
		if(m_native){
			m_native->stopTimer(timerID);
		}
	}

	void FCView::update(){
		if(m_native && !m_native->m_lockUpdate){
			m_native->setAlign(&m_views);
			if (m_oldSize.cx > 0 && m_oldSize.cy > 0){
				m_native->setAnchor(&m_views, m_oldSize);
			}
			m_native->setDock(&m_views);
			m_oldSize = getSize();
            int viewsSize = (int)m_views.size();
            for (int i = 0; i < viewsSize; i++){
                m_views.get(i)->update();
            }
		}
	}
}